package room

import (
	"errors"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) checkStartPublishReqData(data common.SFUStartPublishReqData) error {
	// Check if room ID provided
	if data.RoomId == "" {
		return errors.New("room ID is required in start publish request")
	}

	// Check if user ID provided
	if data.UserId == "" {
		return errors.New("user ID is required in start publish request")
	}

	// Check media information
	if err := ValidateMediaInfo(data.Media); err != nil {
		return errors.New("invalid media information in start publish request")
	}

	// Check if room exists
	if !s.roomMgr.RoomExists(data.RoomId) {
		return errors.New("room does not exist")
	}

	// Check if user is in the room
	if !s.roomMgr.UserExists(data.RoomId, data.UserId) {
		return errors.New("user is not in the room")
	}

	// Check if proucer exists
	if !s.roomMgr.ProducerExists(data.RoomId, data.Media.MediaId) {
		return errors.New("producer does not exist in the room")
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) sendStartPublishResponse(rid string, code int, msg string, connId string,
	data common.SFUStartPublishReqData) {
	resMsg := common.Message{
		Cmd: common.SFU_START_PUBLISH_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: code,
			Msg:  msg,
			Data: common.SFUStartPublishResData{
				RoomId: data.RoomId,
				UserId: data.UserId,
				Media:  data.Media,
			},
		},
	}
	s.dispatcher.Dispatch(resMsg, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) sendStartPublishNotify(rid string, data common.SFUStartPublishReqData,
	connId string) {
	notifyMsg := common.Message{
		Cmd: common.SFU_START_PUBLISH_NOTIFY,
		Rid: rid,
		Data: common.SFUStartPublishNotifyData{
			RoomId: data.RoomId,
			UserId: data.UserId,
			Media:  data.Media,
		},
	}
	s.dispatcher.Dispatch(notifyMsg, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *RoomService) handleStartPublishReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	LOG(msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("Handling SFU Start Publish Request")

	var data common.SFUStartPublishReqData
	if err := mapstructure.Decode(msg.Data, &data); err != nil {
		return errors.New("failed to decode start publish request data: " + err.Error())
	}

	if err := s.checkStartPublishReqData(data); err != nil {
		LOG(msg.Rid).WithError(err).Error("Start publish request data validation failed")
		s.sendStartPublishResponse(msg.Rid, 1, err.Error(), connId, data)
		return nil
	}

	s.sendStartPublishResponse(msg.Rid, 0, "success", connId, data)

	// Notify the room about the new producer
	for _, user := range s.roomMgr.GetUserList(data.RoomId) {
		if user.UserId != data.UserId {
			s.sendStartPublishNotify(msg.Rid, data, user.ConnId)
		}
	}

	return nil
}
